package pl.com.like.sequoia.web.servlets;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;

import javax.activation.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author  Maciej Mitas
 * @version
 */

/**
 * Implementation of DataSource for Byte Array used during preparing reports for mailing.
 */
public class ByteArrayDataSource implements DataSource, Serializable {

	private static final long serialVersionUID = -9028239623152072975L;

	private ByteArrayOutputStream os = null;
	private String contentType;
	private String name;
	private String docFormat;
	private int pageCount;

	private static Logger log = LoggerFactory.getLogger(ByteArrayDataSource.class);

	public ByteArrayDataSource(BufferedInputStream is, String type, String name, String docFormat) {
		this.contentType = type;
		os = new ByteArrayOutputStream();
		try {
			int ch;
			while ((ch = is.read()) != -1)
				// XXX - must be made more efficient by
				// doing buffered reads, rather than one byte reads
				os.write(ch);
			this.name = name;
		} catch (IOException ioex) {
		}
	}

	/**
	 * Create a DataSource from a byte array if contentType = null then contentType = "application/octet-stream"
	 */
	public ByteArrayDataSource(byte[] bytes, String contentType, String name) {
		if (contentType == null)
			this.contentType = "application/octet-stream";
		else
			this.contentType = contentType;
		this.name = name;
		os = new ByteArrayOutputStream();
		try {
			os.write(bytes);
		} catch (IOException e) {
			log.error("could not write to output stream", e);
		}
	}

	public ByteArrayDataSource(ByteArrayOutputStream baos, String contentType, String name) {
		this.docFormat = "";
		this.os = baos;
		if (contentType == null)
			this.contentType = "application/octet-stream";
		else
			this.contentType = contentType;
		this.name = name;
	}

	/**
	 * Create a DataSource from a ByteArrayOutputStream if contentType = null then contentType =
	 * "application/octet-stream"
	 */
	public ByteArrayDataSource(ByteArrayOutputStream baos, String contentType, String name, String docFormat) {
		this.docFormat = docFormat;
		this.os = baos;
		if (contentType == null)
			this.contentType = "application/octet-stream";
		else
			this.contentType = contentType;
		this.name = name;
	}

	/**
	 * Create a DataSource from an input stream
	 */
	public ByteArrayDataSource(InputStream is, String type, String name) {
		this.contentType = type;
		os = new ByteArrayOutputStream();
		try {
			int ch;
			while ((ch = is.read()) != -1)
				// XXX - must be made more efficient by
				// doing buffered reads, rather than one byte reads
				os.write(ch);
			this.name = name;
		} catch (IOException ioex) {
		}
	}

	/**
	 * Create a DataSource from a String
	 */
	public ByteArrayDataSource(String data, String type, String name) {
		try {
			// Assumption that the string contains only ASCII
			// characters! Otherwise just pass a charset into this
			// constructor and use it in getBytes()
			this.os = new ByteArrayOutputStream();
			this.os.write(data.getBytes("iso-8859-1"));
			this.name = name;
		} catch (UnsupportedEncodingException uex) {
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.contentType = type;
	}

	/**
	 * returns content type of the DataSource
	 */
	public String getContentType() {
		return contentType;
	}

	/**
	 * @return Returns the docFormat.
	 */
	public String getDocFormat() {
		return docFormat;
	}

	/**
	 * returns InputStream of the DataSource
	 */
	public InputStream getInputStream() {
		return new ByteArrayInputStream(this.os.toByteArray());
	}

	/**
	 * returns name of the DataSource
	 */
	public String getName() {
		return name;
	}

	/**
	 * returns OutputStream
	 */
	public OutputStream getOutputStream() {
		return os;
	}

	/**
	 * @return Returns the pageCount.
	 */
	public int getPageCount() {
		return pageCount;
	}

	/**
	 * @param docFormat The docFormat to set.
	 */
	public void setDocFormat(String docFormat) {
		this.docFormat = docFormat;
	}

	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @param pageCount The pageCount to set.
	 */
	public void setPageCount(int pageCount) {
		this.pageCount = pageCount;
	}

	public int size() {
		return this.os.toByteArray().length;
	}

	public byte[] toByteArray() {
		return this.os.toByteArray();
	}

}
